package org.springframework.beans.factory.config;

import java.beans.PropertyEditor;
import java.security.AccessControlContext;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;

/**
 * 主要定义了一些BeanFactory的配置功能，
 * 比如通过setParentBeanFactory方法来设置双亲IOC容器，
 * 通过addBeanPostProcessor方法配置Bean后置处理器
 */
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";

    String SCOPE_PROTOTYPE = "prototype";


    /**
     * 设置父BeanFactory
     */
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

    /**
     * 设置类加载器以用于加载bean类
     * 默认是线程上下文类加载器。
     */
    void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);

    /**
     * 返回BeanFactory的ClassLoader
     */
    @Nullable
    ClassLoader getBeanClassLoader();

    /**
     * 设置临时ClassLoader。默认为none，只使用标准bean ClassLoader。
     * 如果是加载时才织入，通常只指定临时ClassLoader，
     * 以确保实际的bean 类尽可能延迟加载。
     * 一旦BeanFactory完成其引导阶段，就会删除临时加载器。
     */
    void setTempClassLoader(@Nullable ClassLoader tempClassLoader);

    /**
     * 如果有的话返回临时ClassLoader
     */
    @Nullable
    ClassLoader getTempClassLoader();

    /**
     * 设置是否缓存bean元数据，例如给定的bean定义（以合并方式）和已解析的bean类。默认打开。
     * <p>关闭此标志以启用bean定义对象的热刷新，特别是bean类。
     * 如果此标志关闭，则任何bean 实例的创建都将重新查询bean类加载器以获取新解析的类.
     */
    void setCacheBeanMetadata(boolean cacheBeanMetadata);

    /**
     * 返回是否缓存bean元数据，例如给定的bean定义（以合并方式）和已解析的bean类。
     */
    boolean isCacheBeanMetadata();

    /**
     * 为bean定义值中的表达式指定解析策略。
     * 默认情况下，BeanFactory中没有活动表达式支持。
     * ApplicationContext通常会在此处设置标准表达式策略，
     * 支持Unified EL兼容样式中的“＃{...}”表达式。
     */
    void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);

    /**
     * 返回bean定义值中表达式的解析策略。
     * @since 3.0
     */
    @Nullable
    BeanExpressionResolver getBeanExpressionResolver();

    /**
     * 指定用于转换属性值的Spring 3.0 ConversionService，作为JavaBeans PropertyEditors的替代方法.
     * @since 3.0
     */
    void setConversionService(@Nullable ConversionService conversionService);

    /**
     * 返回关联的ConversionService（如果有）
     * @since 3.0
     */
    @Nullable
    ConversionService getConversionService();

    /**
     * 添加PropertyEditorRegistrar以应用于所有bean创建过程。
     * 这样的注册器创建新的PropertyEditor实例并在给定的注册表中注册它们
     * 每次创建bean都是新的。这避免了在自定义编辑器上进行同步的需要;
     * 因此最好使用此方法代替{@link #registerCustomEditor}。
     * @param registrar the PropertyEditorRegistrar to register
     */
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

    /**
     * 为给定类型的所有属性注册给定的自定义属性编辑器。在工厂配置期间调用。
     * 请注意，此方法将注册共享自定义编辑器实例;
     * 为了线程安全，将同步对该实例的访问。
     * 最好使用{@link #addPropertyEditorRegistrar}代替此方法，以避免在自定义编辑器上进行同步。
     * @param requiredType type of the property
     * @param propertyEditorClass the {@link PropertyEditor} class to register
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

    /**
     * 使用已在此BeanFactory中注册的自定义编辑器初始化给定的PropertyEditorRegistry。
     * @param registry the PropertyEditorRegistry to initialize
     */
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    /**
     * 设置一个自定义类型转换器，该BeanFactory应该用于转换*bean属性值，构造函数参数值等。
     * 这将覆盖默认的PropertyEditor机制，从而使任何自定义编辑器或自定义编辑器注册表无关紧要。
     * @see #addPropertyEditorRegistrar
     * @see #registerCustomEditor
     * @since 2.5
     */
    void setTypeConverter(TypeConverter typeConverter);

    /**
     * 获取此BeanFactory使用的类型转换器。
     * 这可能是每个调用的新实例，因为TypeConverters通常不线程安全。
     * 如果默认的PropertyEditor机制处于活动状态，
     * 则返回的 TypeConverter将知道已注册的所有自定义编辑器。
     * @since 2.5
     */
    TypeConverter getTypeConverter();

    /**
     * 为嵌入值（例如注释属性）添加String解析器.
     * @param valueResolver the String resolver to apply to embedded values
     * @since 3.0
     */
    void addEmbeddedValueResolver(StringValueResolver valueResolver);

    /**
     * 确定是否已在此 bean工厂中注册了嵌入值解析程序
     * 以通过{@link #resolveEmbeddedValue（String）}应用。
     * @since 4.3
     */
    boolean hasEmbeddedValueResolver();

    /**
     * 解析给定的嵌入值，例如注释属性。
     * @param value the value to resolve
     * @return the resolved value (may be the original value as-is)
     * @since 3.0
     */
    @Nullable
    String resolveEmbeddedValue(String value);

    /**
     * 添加一个新的BeanPostProcessor，它将应用于此工厂创建的bean。在工厂配置期间调用。
     * <p>Note: Post-processors submitted here will be applied in the order of
     * registration; any ordering semantics expressed through implementing the
     * {@link org.springframework.core.Ordered} interface will be ignored. Note
     * that autodetected post-processors (e.g. as beans in an ApplicationContext)
     * will always be applied after programmatically registered ones.
     * @param beanPostProcessor the post-processor to register
     */
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

    /**
     * 返回已注册的BeanPostProcessors的当前数量（如果有）
     */
    int getBeanPostProcessorCount();

    /**
     * Register the given scope, backed by the given Scope implementation.
     * @param scopeName the scope identifier
     * @param scope the backing Scope implementation
     */
    void registerScope(String scopeName, Scope scope);

    /**
     * Return the names of all currently registered scopes.
     * <p>This will only return the names of explicitly registered scopes.
     * Built-in scopes such as "singleton" and "prototype" won't be exposed.
     * @return the array of scope names, or an empty array if none
     * @see #registerScope
     */
    String[] getRegisteredScopeNames();

    /**
     * Return the Scope implementation for the given scope name, if any.
     * <p>This will only return explicitly registered scopes.
     * Built-in scopes such as "singleton" and "prototype" won't be exposed.
     * @param scopeName the name of the scope
     * @return the registered Scope implementation, or {@code null} if none
     * @see #registerScope
     */
    @Nullable
    Scope getRegisteredScope(String scopeName);

    /**
     * 提供与此工厂相关的安全访问控制上下文。
     * @return the applicable AccessControlContext (never {@code null})
     * @since 3.0
     */
    AccessControlContext getAccessControlContext();

    /**
     * 复制给定其他工厂的所有相关配置。
     * 应包括所有标准配置设置以及*BeanPostProcessors，Scopes和工厂特定的内部设置。
     * 不应包含实际bean定义的任何元数据，如BeanDefinition对象和bean名称别名。
     * @param otherFactory the other BeanFactory to copy from
     */
    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);

    /**
     * 给定bean名称，创建别名。我们通常使用此方法来支持XML ID中的非法名称（用于bean名称）。
     * <p>通常在工厂配置期间调用，但也可以用于别名的运行时注册。因此，工厂实现应该同步别名访问。
     * @param beanName the canonical name of the target bean
     * @param alias the alias to be registered for the bean
     * @throws BeanDefinitionStoreException if the alias is already in use
     */
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

    /**
     * 解析在此BeanFactory中注册的所有别名目标名称和别名, 将给定的StringValueResolver应用于它们.
     * <p>The value resolver may for example resolve placeholders
     * in target bean names and even in alias names.
     * @param valueResolver the StringValueResolver to apply
     * @since 2.5
     */
    void resolveAliases(StringValueResolver valueResolver);

    /**
     * Return a merged BeanDefinition for the given bean name,
     * merging a child bean definition with its parent if necessary.
     * Considers bean definitions in ancestor factories as well.
     * @param beanName the name of the bean to retrieve the merged definition for
     * @return a (potentially merged) BeanDefinition for the given bean
     * @throws NoSuchBeanDefinitionException if there is no bean definition with the given name
     * @since 2.5
     */
    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 是否为FactoryBean。
     * @param name the name of the bean to check
     * @return whether the bean is a FactoryBean
     * ({@code false} means the bean exists but is not a FactoryBean)
     * @throws NoSuchBeanDefinitionException if there is no bean with the given name
     * @since 2.5
     */
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

    /**
     * 显式控制指定bean的当前创建状态。 仅限容器内部使用。
     * @param beanName the name of the bean
     * @param inCreation whether the bean is currently in creation
     * @since 3.1
     */
    void setCurrentlyInCreation(String beanName, boolean inCreation);

    /**
     * bean当前是否正在创建
     * @param beanName the name of the bean
     * @return whether the bean is currently in creation
     * @since 2.5
     */
    boolean isCurrentlyInCreation(String beanName);

    /**
     * 注册给定bean的依赖bean，在销毁给定bean之前销毁。
     * @param beanName the name of the bean
     * @param dependentBeanName the name of the dependent bean
     * @since 2.5
     */
    void registerDependentBean(String beanName, String dependentBeanName);

    /**
     * 返回依赖于指定bean的所有bean的名称。
     * @param beanName the name of the bean
     * @return the array of dependent bean names, or an empty array if none
     * @since 2.5
     */
    String[] getDependentBeans(String beanName);

    /**
     * 返回beanName的所有bean的名称
     * @param beanName the name of the bean
     * @return the array of names of beans which the bean depends on,
     * or an empty array if none
     */
    String[] getDependenciesForBean(String beanName);

    /**
     * 根据bean的定义，销毁给定的bean实例，通常是从这个工厂获得的原型实例
     * 在销毁期间出现的任何异常都应该被捕获并记录而不是传播给此方法的调用者。
     * @param beanName the name of the bean definition
     * @param beanInstance the bean instance to destroy
     */
    void destroyBean(String beanName, Object beanInstance);

    /**
     * 销毁当前作用域的原型模式的bean
     *在销毁期间出现的任何异常都应该被捕获并记录而不是传播给此方法的调用者。
     * @param beanName 原型模式bean的名字
     */
    void destroyScopedBean(String beanName);

    /**
     * 销毁BeanFactory中的所有单例bean，包括已经注册的一次性的bean，在关闭BeanFactory时被调用
     * 在销毁期间出现的任何异常都应该被捕获并记录而不是传播给此方法的调用者。
     */
    void destroySingletons();

}
